/****************************************************************************

  

  GLUI User Interface Toolkit

  ---------------------------



     glui.h - Main header for GLUI User Interface Toolkit





          --------------------------------------------------



  Copyright (c) 1998 Paul Rademacher



  This program is freely distributable without licensing fees and is

  provided without guarantee or warrantee expressed or implied. This

  program is -not- in the public domain.



*****************************************************************************/





#ifndef _GLUI_H_

#define _GLUI_H_



//#include <GL/glut.h>
#include <GL/include/glut.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <time.h>



#define GLUI_VERSION 2.01f    /********** Current version **********/



class Arcball;



/********** Do some basic defines *******/

#ifndef false

#define true 1

#define false 0

#endif



#ifndef Byte

#define Byte unsigned char

#endif



#ifndef _RGBC_

class RGBc {

public:

  Byte r, g, b;

    

  void set(Byte r,Byte g,Byte b) {this->r=r;this->g=g;this->b=b;};

    

  RGBc( void ) {};

  RGBc( Byte r, Byte g, Byte b ) { set( r, g, b ); };

};

#define _RGBC_

#endif



/********** List of GLUT callbacks ********/



enum GLUI_Glut_CB_Types { 

  GLUI_GLUT_RESHAPE,

  GLUI_GLUT_KEYBOARD,

  GLUI_GLUT_DISPLAY,

  GLUI_GLUT_MOUSE,

  GLUI_GLUT_MOTION,

  GLUI_GLUT_SPECIAL,

  GLUI_GLUT_PASSIVE_MOTION,  

  GLUI_GLUT_ENTRY,

  GLUI_GLUT_VISIBILITY  

};



/********** List of control types **********/

enum GLUI_Control_Types {

  GLUI_CONTROL_CHECKBOX =1,

  GLUI_CONTROL_BUTTON,

  GLUI_CONTROL_RADIOBUTTON,

  GLUI_CONTROL_RADIOGROUP,

  GLUI_CONTROL_SLIDER,

  GLUI_CONTROL_STATICTEXT,

  GLUI_CONTROL_EDITTEXT,

  GLUI_CONTROL_BITMAP,

  GLUI_CONTROL_PANEL,

  GLUI_CONTROL_SPINNER,

  GLUI_CONTROL_SEPARATOR,

  GLUI_CONTROL_COLUMN,

  GLUI_CONTROL_LISTBOX,

  GLUI_CONTROL_MOUSE_INTERACTION,

  GLUI_CONTROL_ROTATION,

  GLUI_CONTROL_TRANSLATION,

  GLUI_CONTROL_ROLLOUT,

  GLUI_CONTROL_HSLIDER

};





/********* Constants for window placement **********/

#define GLUI_XOFF                       6

#define GLUI_YOFF                       6

#define GLUI_ITEMSPACING                3

#define GLUI_CHECKBOX_SIZE              13

#define GLUI_RADIOBUTTON_SIZE           13

#define GLUI_BUTTON_SIZE                20

#define GLUI_STATICTEXT_SIZE            13

#define GLUI_SEPARATOR_HEIGHT           8

#define GLUI_DEFAULT_CONTROL_WIDTH      100

#define GLUI_DEFAULT_CONTROL_HEIGHT     13 

#define GLUI_EDITTEXT_BOXINNERMARGINX   3

#define GLUI_EDITTEXT_HEIGHT            20

#define GLUI_EDITTEXT_WIDTH             130

#define GLUI_EDITTEXT_MIN_INT_WIDTH     35

#define GLUI_EDITTEXT_MIN_TEXT_WIDTH    50

#define GLUI_PANEL_NAME_DROP            8

#define GLUI_PANEL_EMBOSS_TOP           4

/* #define GLUI_ROTATION_WIDTH            60*/

/*  #define GLUI_ROTATION_HEIGHT           78 */

#define GLUI_ROTATION_WIDTH             50

#define GLUI_ROTATION_HEIGHT            (GLUI_ROTATION_WIDTH+18)

#define GLUI_MOUSE_INTERACTION_WIDTH    50

#define GLUI_MOUSE_INTERACTION_HEIGHT   (GLUI_MOUSE_INTERACTION_WIDTH)+18

#define GLUI_HSLIDER_HEIGHT             16

#define GLUI_HSLIDER_WIDTH              130





/** Different panel control types **/

#define GLUI_PANEL_NONE      0

#define GLUI_PANEL_EMBOSSED  1

#define GLUI_PANEL_RAISED    2





/**  Max # of els in control's float_array  **/

#define GLUI_DEF_MAX_ARRAY  30



/********* The control's 'active' behavior *********/

#define GLUI_CONTROL_ACTIVE_MOUSEDOWN       1

#define GLUI_CONTROL_ACTIVE_PERMANENT       2





/********* Control alignment types **********/

#define GLUI_ALIGN_CENTER   1

#define GLUI_ALIGN_RIGHT    2

#define GLUI_ALIGN_LEFT     3





/********** Limit types - how to limit spinner values *********/

#define GLUI_LIMIT_NONE    0

#define GLUI_LIMIT_CLAMP   1

#define GLUI_LIMIT_WRAP    2





/********** Translation control types ********************/



#define GLUI_TRANSLATION_XY 0

#define GLUI_TRANSLATION_Z  1

#define GLUI_TRANSLATION_X  2

#define GLUI_TRANSLATION_Y  3



#define GLUI_TRANSLATION_LOCK_NONE 0

#define GLUI_TRANSLATION_LOCK_X    1

#define GLUI_TRANSLATION_LOCK_Y    2



/********** How was a control activated? *****************/

#define GLUI_ACTIVATE_MOUSE 1

#define GLUI_ACTIVATE_TAB   2





/********** What type of live variable does a control have? **********/

#define GLUI_LIVE_NONE          0

#define GLUI_LIVE_INT           1

#define GLUI_LIVE_FLOAT         2

#define GLUI_LIVE_TEXT          3

#define GLUI_LIVE_DOUBLE        4

#define GLUI_LIVE_FLOAT_ARRAY   5





/**********  Translation codes  **********/



enum TranslationCodes  {

  GLUI_TRANSLATION_MOUSE_NONE=0,

  GLUI_TRANSLATION_MOUSE_UP,

  GLUI_TRANSLATION_MOUSE_DOWN,

  GLUI_TRANSLATION_MOUSE_LEFT,

  GLUI_TRANSLATION_MOUSE_RIGHT,

  GLUI_TRANSLATION_MOUSE_UP_LEFT,

  GLUI_TRANSLATION_MOUSE_UP_RIGHT,

  GLUI_TRANSLATION_MOUSE_DOWN_LEFT,

  GLUI_TRANSLATION_MOUSE_DOWN_RIGHT

};



/************ A string type for us to use **********/

/*  typedef char  GLUI_String[300]; */

class GLUI_String

{

public:

  char string[300];



  char &operator[]( int i ) {

    return string[i];

  }



  operator char*() { return (char*) &string[0]; };

  /*    operator void*() { return (void*) &string[0]; }; */



  GLUI_String( void ) {

    string[0] = '\0';

  }



  GLUI_String( char *text ) {

    strcpy( string, text );

  }

};





/********* Pre-declare the various classes *********/

class GLUI;

class GLUI_Control;

class GLUI_Listbox;

class GLUI_Rotation;

class GLUI_Translation;

class GLUI_Mouse_Interaction;

class GLUI_Checkbox;

class GLUI_HSlider;

class GLUI_Button;

class GLUI_StaticText;

class GLUI_Bitmap;

class GLUI_EditText;

class GLUI_Node;

class GLUI_Main;

class GLUI_Panel;

class GLUI_Spinner;

class GLUI_RadioButton;

class GLUI_RadioGroup;

class GLUI_Separator;

class GLUI_Column;

class GLUI_Master;

class GLUI_Glut_Window;

class GLUI_Rollout;







/*** Flags for GLUI class constructor ***/

#define  GLUI_SUBWINDOW          ((long)(1<< 1))

#define  GLUI_SUBWINDOW_TOP      ((long)(1<< 2))

#define  GLUI_SUBWINDOW_BOTTOM   ((long)(1<< 3))

#define  GLUI_SUBWINDOW_LEFT     ((long)(1<< 4))

#define  GLUI_SUBWINDOW_RIGHT    ((long)(1<< 5))



/*** Codes for different type of edittext boxes and spinners ***/

#define GLUI_EDITTEXT_TEXT             1

#define GLUI_EDITTEXT_INT              2

#define GLUI_EDITTEXT_FLOAT            3

#define GLUI_SPINNER_INT               GLUI_EDITTEXT_INT

#define GLUI_SPINNER_FLOAT             GLUI_EDITTEXT_FLOAT

#define GLUI_HSLIDER_INT               GLUI_EDITTEXT_INT

#define GLUI_HSLIDER_FLOAT             GLUI_EDITTEXT_FLOAT







/*** Definition of callbacks ***/

typedef void (*GLUI_Update_CB) (int id);

typedef void (*Int1_CB)        (int);

typedef void (*Int2_CB)        (int, int);

typedef void (*Int3_CB)        (int, int, int);

typedef void (*Int4_CB)        (int, int, int, int);



				 



/************************************************************/

/*                                                          */

/*          Base class, for hierarchical relationships      */

/*                                                          */

/************************************************************/



class GLUI_Node {

protected:

  GLUI_Node *parent_node;

  GLUI_Node *child_head;

  GLUI_Node *child_tail;

  GLUI_Node *next_sibling;

  GLUI_Node *prev_sibling;



public:

  GLUI_Node *first_sibling( void );

  GLUI_Node *last_sibling( void );

  GLUI_Node *prev( void );

  GLUI_Node *next( void );

  GLUI_Node *first_child( void )   { return child_head; };

  GLUI_Node *last_child( void )    { return child_tail; };

  GLUI_Node *parent(void)          { return parent_node; };



  void      link_this_to_parent_last( GLUI_Node *parent );

  void      link_this_to_parent_first( GLUI_Node *parent );

  void      link_this_to_sibling_next( GLUI_Node *sibling );

  void      link_this_to_sibling_prev( GLUI_Node *sibling );

  void      unlink( void );



  void dump( FILE *out, char *name ) {

    fprintf( out, "GLUI_node: %s\n", name );

    fprintf( out, "   parent: %p     child_head: %p    child_tail: %p\n",

	     parent_node, child_head, child_tail );

    fprintf( out, "   next: %p       prev: %p\n", next_sibling, prev_sibling );

  }



  GLUI_Node( void ) { 

    parent_node= child_head = child_tail = next_sibling = prev_sibling = NULL;

  }; 



  friend GLUI_Rollout;

  friend GLUI_Main;

};







/************************************************************/

/*                                                          */

/*                  Standard Bitmap stuff                   */

/*                                                          */

/************************************************************/



enum GLUI_StdBitmaps_Codes {

  GLUI_STDBITMAP_CHECKBOX_OFF=0,

  GLUI_STDBITMAP_CHECKBOX_ON,

  GLUI_STDBITMAP_RADIOBUTTON_OFF,

  GLUI_STDBITMAP_RADIOBUTTON_ON,

  GLUI_STDBITMAP_UP_ARROW,

  GLUI_STDBITMAP_DOWN_ARROW,

  GLUI_STDBITMAP_LEFT_ARROW,

  GLUI_STDBITMAP_RIGHT_ARROW,

  GLUI_STDBITMAP_TROUGH,

  GLUI_STDBITMAP_SPINNER_UP_OFF,

  GLUI_STDBITMAP_SPINNER_UP_ON,

  GLUI_STDBITMAP_SPINNER_DOWN_OFF,

  GLUI_STDBITMAP_SPINNER_DOWN_ON,



  GLUI_STDBITMAP_CHECKBOX_OFF_DIS,    /*** Disactivated control bitmaps ***/

  GLUI_STDBITMAP_CHECKBOX_ON_DIS,

  GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS,

  GLUI_STDBITMAP_RADIOBUTTON_ON_DIS,

  GLUI_STDBITMAP_SPINNER_UP_DIS,

  GLUI_STDBITMAP_SPINNER_DOWN_DIS,

  GLUI_STDBITMAP_LISTBOX_UP,

  GLUI_STDBITMAP_LISTBOX_DOWN,

  GLUI_STDBITMAP_LISTBOX_UP_DIS,

  /***

    GLUI_STDBITMAP_SLIDER_TAB,

    ***/

  GLUI_STDBITMAP_NUM_ITEMS

};





/************ Image Bitmap arrays **********/

extern int glui_img_checkbox_0[];

extern int glui_img_checkbox_1[];

extern int glui_img_radiobutton_0[];

extern int glui_img_radiobutton_1[];

extern int glui_img_uparrow[];

extern int glui_img_downarrow[];

extern int glui_img_leftarrow[];

extern int glui_img_rightarrow[];

extern int glui_img_trough[];

extern int glui_img_spinup_0[];

extern int glui_img_spinup_1[];

extern int glui_img_spindown_0[];

extern int glui_img_spindown_1[];

extern int glui_img_checkbox_0_dis[];

extern int glui_img_checkbox_1_dis[];

extern int glui_img_radiobutton_0_dis[];

extern int glui_img_radiobutton_1_dis[];

extern int glui_img_spinup_dis[];

extern int glui_img_spindown_dis[];

extern int glui_img_listbox_up[];

extern int glui_img_listbox_down[];

extern int glui_img_listbox_up_dis[];



extern int *bitmap_arrays[];







/************************************************************/

/*                                                          */

/*                  Class GLUI_Bitmap                       */

/*                                                          */

/************************************************************/

class GLUI_Bitmap 

{

public:

  unsigned char *pixels;

  int            w, h;

  

  void load_from_array( int *array );



  GLUI_Bitmap( void ) {

    pixels = NULL;

    w      = 0;

    h      = 0;

  }

};









/************************************************************/

/*                                                          */

/*                  Class GLUI_StdBitmap                    */

/*                                                          */

/************************************************************/

class GLUI_StdBitmaps

{

public:

  GLUI_Bitmap bitmaps[ GLUI_STDBITMAP_NUM_ITEMS ];



  void draw( int bitmap_num, int x, int y );

  

  GLUI_StdBitmaps( void ) {

    int i;



    for( i=0; i<GLUI_STDBITMAP_NUM_ITEMS; i++ ) {

      bitmaps[i].load_from_array( bitmap_arrays[i] );

    }

  }

};









/************************************************************/

/*                                                          */

/*                     Master GLUI Class                    */

/*                                                          */

/************************************************************/

class GLUI_Master_Object {

private:

  GLUI_Node     glut_windows;

  void (*glut_idle_CB)(void);



  void                add_cb_to_glut_window(int window,int cb_type,void *cb);

  

public:

  GLUI_Node     gluis;

  GLUI_Control *active_control, *curr_left_button_glut_menu;

  GLUI         *active_control_glui;

  int           glui_id_counter;



  GLUI_Glut_Window   *find_glut_window( int window_id );



  void           set_glutIdleFunc(void (*f)(void));



  /**************

    void (*glut_keyboard_CB)(unsigned char, int, int);

    void (*glut_reshape_CB)(int, int);

    void (*glut_special_CB)(int, int, int);

    void (*glut_mouse_CB)(int,int,int,int);

    

    void (*glut_passive_motion_CB)(int,int);

    void (*glut_visibility_CB)(int);

    void (*glut_motion_CB)(int,int);

    void (*glut_display_CB)(void);

    void (*glut_entry_CB)(int);

    **********/



  void  set_left_button_glut_menu_control( GLUI_Control *control );





  /********** GLUT callthroughs **********/

  /* These are the glut callbacks that we do not handle */



  void set_glutReshapeFunc(void (*f)(int width, int height));

  void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));

  void set_glutSpecialFunc(void (*f)(int key, int x, int y));

  void set_glutMouseFunc(void (*f)(int, int, int, int ));



  void set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);};

  void set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value)

    { ::glutTimerFunc(millis,f,value);};

  void set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);};

  void set_glutSpaceballMotionFunc(Int3_CB f)  {glutSpaceballMotionFunc(f);};

  void set_glutSpaceballRotateFunc(Int3_CB f)  {glutSpaceballRotateFunc(f);};

  void set_glutSpaceballButtonFunc(Int2_CB f)  {glutSpaceballButtonFunc(f);};

  void set_glutTabletMotionFunc(Int2_CB f)        {glutTabletMotionFunc(f);};

  void set_glutTabletButtonFunc(Int4_CB f)        {glutTabletButtonFunc(f);};

  /*    void set_glutWindowStatusFunc(Int1_CB f)        {glutWindowStatusFunc(f);}; */

  void set_glutMenuStatusFunc(Int3_CB f)            {glutMenuStatusFunc(f);};

  void set_glutMenuStateFunc(Int1_CB f)              {glutMenuStateFunc(f);};

  void set_glutButtonBoxFunc(Int2_CB f)              {glutButtonBoxFunc(f);};

  void set_glutDialsFunc(Int2_CB f)                      {glutDialsFunc(f);};  

  



  GLUI          *create_glui( char *name, long flags=0, int x=-1, int y=-1 ); 

  GLUI          *create_glui_subwindow( int parent_window, long flags=0 );

  GLUI          *find_glui_by_window_id( int window_id );

  void           get_viewport_area( int *x, int *y, int *w, int *h );

  void           auto_set_viewport( void );

  void           close_all( void );

  void           sync_live_all( void );



  void           reshape( void );



  float          get_version( void ) { return GLUI_VERSION; };



  friend void    glui_idle_func(void);



  GLUI_Master_Object( void ) {

    glut_idle_CB    = NULL;

    glui_id_counter = 1;

  }

};



extern GLUI_Master_Object GLUI_Master;







/************************************************************/

/*                                                          */

/*              Class for managing a GLUT window            */

/*                                                          */

/************************************************************/



class GLUI_Glut_Window : public GLUI_Node {

public:

  int    glut_window_id;



  /*********** Pointers to GLUT callthrough functions *****/

  void (*glut_keyboard_CB)(unsigned char, int, int);

  void (*glut_special_CB)(int, int, int);

  void (*glut_reshape_CB)(int, int);

  void (*glut_passive_motion_CB)(int,int);

  void (*glut_mouse_CB)(int,int,int,int);

  void (*glut_visibility_CB)(int);

  void (*glut_motion_CB)(int,int);

  void (*glut_display_CB)(void);

  void (*glut_entry_CB)(int);



  GLUI_Glut_Window( void ) {

    glut_display_CB         = NULL;

    glut_reshape_CB         = NULL;

    glut_keyboard_CB        = NULL;

    glut_special_CB         = NULL;

    glut_mouse_CB           = NULL;

    glut_motion_CB          = NULL;

    glut_passive_motion_CB  = NULL;

    glut_entry_CB           = NULL;

    glut_visibility_CB      = NULL;

    glut_window_id          = 0;

  };

};







/************************************************************/

/*                                                          */

/*              Main GLUI class (not user-level)            */

/*                                                          */

/************************************************************/



class GLUI_Main : public GLUI_Node {

protected:

  /*** Variables ***/

  int           main_gfx_window_id;

  int           mouse_button_down;

  int           glut_window_id;

  int           top_level_glut_window_id;

  GLUI_Control *active_control;

  GLUI_Control *mouse_over_control;

  GLUI_Panel   *main_panel;

  int           curr_cursor;

  int           w, h;

  long          flags; 

  int           closing;

  int           parent_window;

  int           glui_id;



  /********** Friend classes *************/



  friend GLUI_Control;

  friend GLUI_Rotation;

  friend GLUI_Translation;

  friend GLUI;

  friend GLUI_Master_Object;





  /********** Misc functions *************/



  GLUI_Control  *find_control( int x, int y );

  GLUI_Control  *find_next_control( GLUI_Control *control );

  GLUI_Control  *find_next_control_rec( GLUI_Control *control );

  GLUI_Control  *find_next_control_( GLUI_Control *control );

  GLUI_Control  *find_prev_control( GLUI_Control *control );

  void           create_standalone_window( char *name, int x=-1, int y=-1 );

  void           create_subwindow( int parent,int window_alignment );

  void           setup_default_glut_callbacks( void );



  void           mouse(int button, int state, int x, int y);

  void           keyboard(unsigned char key, int x, int y);

  void           special(int key, int x, int y);

  void           passive_motion(int x, int y);

  void           reshape( int w, int h );

  void           visibility(int state);

  void           motion(int x, int y);

  void           entry(int state);

  void           display( void );

  void           idle(void);



  void (*glut_mouse_CB)(int, int, int, int);

  void (*glut_keyboard_CB)(unsigned char, int, int);

  void (*glut_special_CB)(int, int, int);

  void (*glut_reshape_CB)(int, int);



  

  /*********** Friend functions and classes **********/



  friend void    glui_mouse_func(int button, int state, int x, int y);

  friend void    glui_keyboard_func(unsigned char key, int x, int y);

  friend void    glui_special_func(int key, int x, int y);

  friend void    glui_passive_motion_func(int x, int y);

  friend void    glui_reshape_func( int w, int h );

  friend void    glui_visibility_func(int state);

  friend void    glui_motion_func(int x, int y);

  friend void    glui_entry_func(int state);

  friend void    glui_display_func( void );

  friend void    glui_idle_func(void);



  friend void    glui_parent_window_reshape_func( int w, int h );

  friend void    glui_parent_window_keyboard_func( unsigned char, int, int );

  friend void    glui_parent_window_special_func( int, int, int );

  friend void    glui_parent_window_mouse_func( int, int, int, int );





  /*********** Controls ************/

  GLUI_Control *controls;

  int           num_controls;



  int           add_control( GLUI_Node *parent, GLUI_Control *control );





  /********** Constructors and Destructors ***********/



  GLUI_Main( void );



public:

  GLUI_StdBitmaps  std_bitmaps;

  GLUI_String      window_name;

  RGBc             bkgd_color;

  float            bkgd_color_f[3];



  void            *font;

  int              curr_modifiers;



  void         adjust_glut_xy( int &x, int &y ) { y = h-y; x = x; };

  void         activate_control( GLUI_Control *control, int how );

  void         align_controls( GLUI_Control *control );

  void         restore_draw_buffer( int buffer_state );

  void         disactivate_current_control( void );

  void         draw_raised_box( int x, int y, int w, int h );

  void         draw_lowered_box( int x, int y, int w, int h );

  int          set_front_draw_buffer( void );

  void         post_update_main_gfx( void );

  void         pack_controls( void );

  void         close_internal( void );

  void         check_subwindow_position( void );

  void	       set_ortho_projection( void );

  void	       set_viewport( void );

  void         refresh( void );

};













/************************************************************/

/*                                                          */

/*       GLUI_Control: base class for all controls          */

/*                                                          */

/************************************************************/



class GLUI_Control : public GLUI_Node {

public:



  int             w, h;                        /* dimensions of control */

  int             x_abs, y_abs;

  int             x_off, y_off_top, y_off_bot; /* INNER margins, by which

						  child controls are indented */

  int             contain_x, contain_y; 

  int             contain_w, contain_h;

  /* if this is a container control (e.g., 

     radiogroup or panel) this indicated dimensions

     of inner area in which controls reside */

  int             active, active_type, can_activate;

  int             spacebar_mouse_click;

  long            user_id, type;

  int             is_container;  /* Is this a container class (e.g., panel) */

  int             alignment;

  GLUI_Update_CB  callback;

  void            *ptr_val;                              /* A pointer value */

  float           float_val;                               /* A float value */

  int             enabled;                   /* Is this control grayed out? */

  int             int_val;                              /* An integer value */

  float           float_array_val[GLUI_DEF_MAX_ARRAY];

  int             state;

  GLUI_String     name;                         /* The name of this control */

  GLUI_String     text;              

  GLUI           *glui;

  void           *font;

  int             live_type, live_inited;

  int             last_live_int;   /* last value that live var known to have */

  float           last_live_float;

  GLUI_String     last_live_text;

  float           last_live_float_array[GLUI_DEF_MAX_ARRAY];

  int             float_array_size;



  int             collapsible, is_open;

  GLUI_Node       collapsed_node;

  int             hidden; /* Collapsed controls (and children) are hidden */



  /*** Get/Set values ***/



  virtual void   set_name( char *string );

  virtual void   set_int_val( int new_int )         { int_val = new_int; output_live(true); };

  virtual void   set_float_val( float new_float )   { float_val = new_float; output_live(true); };

  virtual void   set_ptr_val( void *new_ptr )       { ptr_val = new_ptr; output_live(true); };

  virtual void   set_float_array_val( float *array_ptr );



  virtual float  get_float_val( void )              { return float_val; };

  virtual int    get_int_val( void )                { return int_val; };

  virtual void   get_float_array_val( float *array_ptr );

  

  virtual int mouse_down_handler( int local_x, int local_y ) 

    { local_x = local_y = local_x + local_y; return false; };

  virtual int mouse_up_handler( int local_x, int local_y, int inside )

    { local_x = local_y = inside = local_x+local_y+inside; return false; };

  virtual int mouse_held_down_handler( int local_x, int local_y, int inside)

    { local_x = local_y = inside = local_x+local_y+inside; return false; };

  virtual int key_handler( unsigned char key, int modifiers )

    { key = key; modifiers = modifiers; return false; };

  virtual int special_handler( int key,int modifiers )

    { key = modifiers = key+modifiers; return false; };



  virtual void update_size( void )     { };

  virtual void idle( void )            { };

  virtual int  mouse_over( int state, int x, int y )

		{ state = x = y = state+x+y; return false; };

  

  virtual void enable( void ); 

  virtual void disable( void );

  virtual void activate( int how )     { how = how; active = true; };

  virtual void disactivate( void )     { active = false; };



  void         hide_internal( int recurse );

  void         unhide_internal( int recurse );



  int          can_draw( void ) { return (glui != NULL && hidden == false); };



  virtual void align( void );

  void         pack( int x, int y );    /* Recalculate positions and offsets */

  void         pack_old( int x, int y );    

  void         draw_recursive( int x, int y );

  int          set_to_glut_window( void );

  void         restore_window( int orig );

  void         translate_and_draw_front( void );

  void         translate_to_origin( void ) 

    {glTranslatef((float)x_abs+.5,(float)y_abs+.5,0.0);};

  virtual void draw( int x, int y )=0;

  void         set_font( void *new_font );

  void        *get_font( void );

  int          string_width( char *text );

  int          char_width( char c );



  void         draw_name( int x, int y );

  void         draw_box_inwards_outline( int x_min, int x_max, 

					 int y_min, int y_max );

  void         draw_box( int x_min, int x_max, int y_min, int y_max,

			 float r, float g, float b );

  void         draw_bkgd_box( int x_min, int x_max, int y_min, int y_max );

  void         draw_emboss_box( int x_min, int x_max,int y_min,int y_max);

  void         draw_string( char *text );

  void         draw_char( char c );

  void         draw_active_box( int x_min, int x_max, int y_min, int y_max );

  void         set_to_bkgd_color( void );

	

  void         set_w( int new_w );

  void         set_h( int new_w );

  void         set_alignment( int new_align );

  void         sync_live( int recurse, int draw );  /* Reads live variable */

  void         init_live( void );

  void         output_live( int update_main_gfx );        /** Writes live variable **/

  virtual void set_text( char *t )   { t = t; };

  void         execute_callback( void );

  void         get_this_column_dims( int *col_x, int *col_y, 

				     int *col_w, int *col_h, 

				     int *col_x_off, int *col_y_off );

  virtual int  needs_idle( void );



  GLUI_Control(void) {

    x_off          = GLUI_XOFF;

    y_off_top      = GLUI_YOFF;

    y_off_bot      = GLUI_YOFF;

    x_abs          = GLUI_XOFF;

    y_abs          = GLUI_YOFF;

    state          = 0;

    active         = false;

    enabled        = true;

    int_val        = 0;

    last_live_int  = 0;

    float_array_size = 0;

    sprintf( (char*)name, "Control: %p", this );

    float_val      = 0.0;

    last_live_float = 0.0;

    ptr_val        = NULL;

    glui           = NULL;

    w              = GLUI_DEFAULT_CONTROL_WIDTH;

    h              = GLUI_DEFAULT_CONTROL_HEIGHT;

    font           = NULL;

    active_type    = GLUI_CONTROL_ACTIVE_MOUSEDOWN;

    alignment      = GLUI_ALIGN_LEFT;

    is_container   = false;

    can_activate   = true;         /* By default, you can activate a control */

    spacebar_mouse_click = true;    /* Does spacebar simulate a mouse click? */

    live_type      = GLUI_LIVE_NONE;

    strcpy( (char*)text, "" );

    strcpy( (char*)last_live_text, "" );

    live_inited    = false;

    collapsible    = false;

    is_open        = true;

    hidden         = false;



    int i;

    for( i=0; i<GLUI_DEF_MAX_ARRAY; i++ )

      float_array_val[i] = last_live_float_array[i] = 0.0;

  };



  ~GLUI_Control();

};









/************************************************************/

/*                                                          */

/*               Button class (container)                   */

/*                                                          */

/************************************************************/



class GLUI_Button : public GLUI_Control

{

public:

  int currently_inside;



  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int same );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  

  void draw( int x, int y );

  void draw_pressed( void );

  void draw_unpressed( void );

  void draw_text( int sunken );



  void update_size( void );



  GLUI_Button( void ) {

    sprintf( name, "Button: %p", this );

    type         = GLUI_CONTROL_BUTTON;

    h            = GLUI_BUTTON_SIZE;

    w            = 100;

    alignment    = GLUI_ALIGN_CENTER;

    can_activate = true;

  };

};







/************************************************************/

/*                                                          */

/*               Checkbox class (container)                 */

/*                                                          */

/************************************************************/



class GLUI_Checkbox : public GLUI_Control

{

public:

  int  orig_value, currently_inside;

  int  text_x_offset;



  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int inside );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  

  void update_size( void );



  void draw( int x, int y );



  void draw_active_area( void );

  void draw_checked( void );

  void draw_unchecked( void );

  void draw_X( void );

  void draw_empty_box( void );

  void set_int_val( int new_val );



  GLUI_Checkbox( void ) {

    sprintf( name, "Checkbox: %p", this );

    type           = GLUI_CONTROL_CHECKBOX;

    w              = 100;

    h              = GLUI_CHECKBOX_SIZE;

    orig_value     = -1;

    text_x_offset  = 18;

    can_activate   = true;

    live_type      = GLUI_LIVE_INT;   /* This control has an 'int' live var */

  };

};





/************************************************************/

/*                                                          */

/*               Column class                               */

/*                                                          */

/************************************************************/



class GLUI_Column : public GLUI_Control

{

public:

  void draw( int x, int y );



  GLUI_Column( void ) {

    type         = GLUI_CONTROL_COLUMN;

    w            = 0;

    h            = 0;

    int_val      = 0;

    can_activate = false;

  };

};







/************************************************************/

/*                                                          */

/*               Panel class (container)                    */

/*                                                          */

/************************************************************/



class GLUI_Panel : public GLUI_Control

{

public:

  void draw( int x, int y );

  void set_name( char *text );

  void set_type( int new_type );



  void update_size( void );



  GLUI_Panel( void ) {

    type         = GLUI_CONTROL_PANEL;

    w            = 300;

    h            = GLUI_DEFAULT_CONTROL_HEIGHT + 7;

    int_val      = GLUI_PANEL_EMBOSSED;

    alignment    = GLUI_ALIGN_CENTER;

    is_container = true; 

    can_activate = false;

    strcpy( name, "" );

  };

};





/************************************************************/

/*                                                          */

/*               Panel class (container)                    */

/*                                                          */

/************************************************************/



class GLUI_Rollout : public GLUI_Panel

{

  /*  private: */

  /*  	GLUI_Panel panel; */

public:

  int          currently_inside, initially_inside;

  GLUI_Button  button;



  void draw( int x, int y );

  void draw_pressed( void );

  void draw_unpressed( void );

  int mouse_down_handler( int local_x, int local_y );

  int mouse_up_handler( int local_x, int local_y, int inside );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

		

  void  open( void ); 

  void  close( void );



    /*   void set_name( char *text )   { panel.set_name( text ); }; */

  void update_size( void );



  GLUI_Rollout( void ) {

    currently_inside = false;

    initially_inside = false;

    can_activate     = true;

    is_container     = true;

    type             = GLUI_CONTROL_ROLLOUT;

    h                = GLUI_DEFAULT_CONTROL_HEIGHT + 7;

    w                = GLUI_DEFAULT_CONTROL_WIDTH;

    y_off_top        = 21;

    collapsible      = true;

    strcpy( name, "" );

  };

};





/************************************************************/

/*                                                          */

/*                     User-Level GLUI class                */

/*                                                          */

/************************************************************/



class GLUI : public GLUI_Main {

private:

public:

  void  add_column( int draw_bar = true );

  void  add_column_to_panel( GLUI_Panel *panel, int draw_bar = true );



  void  add_separator( void );

  void  add_separator_to_panel( GLUI_Panel *panel );



  GLUI_RadioGroup 

    *add_radiogroup( int *live_var=NULL,

		     int user_id=-1,GLUI_Update_CB callback=NULL);



  GLUI_RadioGroup 

    *add_radiogroup_to_panel(  GLUI_Panel *panel,

			       int *live_var=NULL,

			       int user_id=-1, GLUI_Update_CB callback=NULL );

  GLUI_RadioButton

    *add_radiobutton_to_group(  GLUI_RadioGroup *group,

				char *name );



  GLUI_Listbox *add_listbox( char *name, int *live_var=NULL,

			     int id=-1, GLUI_Update_CB callback=NULL	);

  GLUI_Listbox *add_listbox_to_panel( GLUI_Panel *panel,

				      char *name, int *live_var=NULL,

				      int id=-1, GLUI_Update_CB callback=NULL);



  GLUI_Rotation *add_rotation( char *name, float *live_var=NULL,

			       int id=-1, GLUI_Update_CB callback=NULL	);

  GLUI_Rotation *add_rotation_to_panel( GLUI_Panel *panel,

					char *name, float *live_var=NULL,

					int id=-1, GLUI_Update_CB callback=NULL);

  

  GLUI_Translation *add_translation( char *name,

				     int trans_type, float *live_var=NULL,

				     int id=-1, GLUI_Update_CB callback=NULL	);

  GLUI_Translation *add_translation_to_panel( 

					     GLUI_Panel *panel, char *name, 

					     int trans_type, float *live_var=NULL,

					     int id=-1, GLUI_Update_CB callback=NULL);

  

  GLUI_Checkbox  *add_checkbox( char *name, 

				int *live_var=NULL,

				int id=-1, GLUI_Update_CB callback=NULL);

  GLUI_Checkbox  *add_checkbox_to_panel( GLUI_Panel *panel, char *name, 

					 int *live_var=NULL, int id=-1, 

					 GLUI_Update_CB callback=NULL);



  GLUI_Button  *add_button( char *name, int id=-1, 

			    GLUI_Update_CB callback=NULL);

  GLUI_Button  *add_button_to_panel( GLUI_Panel *panel, char *name, 

				     int id=-1, GLUI_Update_CB callback=NULL );



  GLUI_StaticText  *add_statictext( char *name );

  GLUI_StaticText  *add_statictext_to_panel( GLUI_Panel *panel, char *name );



  GLUI_EditText  *add_edittext( char *name, 

				int data_type=GLUI_EDITTEXT_TEXT,

				void *live_var=NULL,

				int id=-1, GLUI_Update_CB callback=NULL	);

  GLUI_EditText  *add_edittext_to_panel( GLUI_Panel *panel, 

					 char *name,

					 int data_type=GLUI_EDITTEXT_TEXT,

					 void *live_var=NULL, int id=-1, 

					 GLUI_Update_CB callback=NULL );



  GLUI_Spinner  *add_spinner( char *name, 

			      int data_type=GLUI_SPINNER_INT,

			      void *live_var=NULL,

			      int id=-1, GLUI_Update_CB callback=NULL );

  GLUI_Spinner  *add_spinner_to_panel( GLUI_Panel *panel, 

				       char *name,

				       int data_type=GLUI_SPINNER_INT,

				       void *live_var=NULL,

				       int id=-1,

				       GLUI_Update_CB callback=NULL );



  GLUI_HSlider  *add_slider(int resizable=false,

			      int data_type=GLUI_HSLIDER_INT,

			      void *live_var=NULL,

			      int id=-1, GLUI_Update_CB callback=NULL );

  GLUI_HSlider  *add_slider_to_panel( GLUI_Panel *panel, 

				       int resizable=false,

				       int data_type=GLUI_HSLIDER_INT,

				       void *live_var=NULL,

				       int id=-1,

				       GLUI_Update_CB callback=NULL );



  GLUI_Panel     *add_panel( char *name, int type=GLUI_PANEL_EMBOSSED );

  GLUI_Panel     *add_panel_to_panel( GLUI_Panel *panel, char *name, 

				      int type=GLUI_PANEL_EMBOSSED );



  GLUI_Rollout   *add_rollout( char *name, int open=true );

  GLUI_Rollout   *add_rollout_to_panel( GLUI_Panel *panel, char *name, int open=true );



  void            set_main_gfx_window( int window_id );

  int             get_glut_window_id( void ) { return glut_window_id; };

  

  void            enable( void ) { main_panel->enable(); };

  void            disable( void );



  void            sync_live( void );



  void            close( void );



  void            show( void );

  void            hide( void );

 

  /***** GLUT callback setup functions *****/

  /*

    void set_glutDisplayFunc(void (*f)(void));

    void set_glutReshapeFunc(void (*f)(int width, int height));

    void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));

    void set_glutSpecialFunc(void (*f)(int key, int x, int y));

    void set_glutMouseFunc(void (*f)(int button, int state, int x, int y));

    void set_glutMotionFunc(void (*f)(int x, int y));

    void set_glutPassiveMotionFunc(void (*f)(int x, int y));

    void set_glutEntryFunc(void (*f)(int state));

    void set_glutVisibilityFunc(void (*f)(int state));

    void set_glutInit( int *argcp, char **argv );

    void set_glutInitWindowSize(int width, int height);

    void set_glutInitWindowPosition(int x, int y);

    void set_glutInitDisplayMode(unsigned int mode);

    int  set_glutCreateWindow(char *name);

    */



  /***** Constructors and desctructors *****/



  int init( char *name, long flags, int x, int y, int parent_window );

};









/************************************************************/

/*                                                          */

/*               EditText class                             */

/*                                                          */

/************************************************************/



class GLUI_EditText : public GLUI_Control

{

public:

  int                 has_limits;

  int                 data_type;

  GLUI_String         orig_text;

  int                 insertion_pt;

  int                 title_x_offset;

  int                 text_x_offset;

  int                 substring_start; /*substring that gets displayed in box*/

  int                 substring_end;  

  int                 sel_start, sel_end;  /* current selection */

  int                 num_periods;

  int                 last_insertion_pt;

  float               float_low, float_high;

  int                 int_low, int_high;

  GLUI_Spinner       *spinner;

  int                 debug;

  int                 draw_text_only;





  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int same );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  int  special_handler(	int key,int modifiers );

  

  void activate( int how );

  void disactivate( void );



  void draw( int x, int y );



  int  mouse_over( int state, int x, int y );



  int  find_word_break( int start, int direction );

  int  substring_width( int start, int end );

  void clear_substring( int start, int end );

  int  find_insertion_pt( int x, int y );

  int  update_substring_bounds( void );

  void update_and_draw_text( void );

  void draw_text( int x, int y );

  void draw_insertion_pt( void );

  void set_numeric_text( void );

  void update_x_offsets( void );

  void update_size( void );



  void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);

  void set_int_limits( int low, int high, int limit_type=GLUI_LIMIT_CLAMP );

  void set_float_val( float new_val );

  void set_int_val( int new_val );

  void set_text( char *text );

  char *get_text( void )         { return text; };  



  void dump( FILE *out, char *text );



  GLUI_EditText( void ) {

    type                  = GLUI_CONTROL_EDITTEXT;

    h                     = GLUI_EDITTEXT_HEIGHT;

    w                     = GLUI_EDITTEXT_WIDTH;

    title_x_offset        = 0;

    text_x_offset         = 55;

    insertion_pt          = -1;

    last_insertion_pt     = -1;

    name[0]               = '\0';

    substring_start       = 0;

    data_type             = GLUI_EDITTEXT_TEXT;

    substring_end         = 2;

    num_periods           = 0;

    has_limits            = GLUI_LIMIT_NONE;

    sel_start             = 0;

    sel_end               = 0;

    active_type           = GLUI_CONTROL_ACTIVE_PERMANENT;

    can_activate          = true;

    spacebar_mouse_click  = false;

    spinner               = NULL;

    debug                 = false;

    draw_text_only        = false;

  };

};









/************************************************************/

/*                                                          */

/*              RadioGroup class (container)                */

/*                                                          */

/************************************************************/



class GLUI_RadioGroup : public GLUI_Control

{

public:

  int  num_buttons;



  void draw( int x, int y );

  void set_name( char *text );

  void set_int_val( int int_val ); 

  void set_selected( int int_val );



  void draw_group( int translate );



  GLUI_RadioGroup( void ) {

    type          = GLUI_CONTROL_RADIOGROUP;

    x_off         = 0;

    y_off_top     = 0;

    y_off_bot     = 0;

    is_container  = true;

    w             = 300;

    h             = 300;

    num_buttons   = 0;

    name[0]       = '\0';

    can_activate  = false;

    live_type     = GLUI_LIVE_INT;

  };

};







/************************************************************/

/*                                                          */

/*               RadioButton class (container)              */

/*                                                          */

/************************************************************/



class GLUI_RadioButton : public GLUI_Control

{

public:

  int orig_value, currently_inside;

  int text_x_offset;



  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int inside );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  

  void draw( int x, int y );

  void update_size( void );



  void draw_active_area( void );

  void draw_checked( void );

  void draw_unchecked( void );

  void draw_O( void );



  GLUI_RadioGroup *group;



  GLUI_RadioButton( void ) {

    sprintf( name, "RadioButton: %p", this );

    type           = GLUI_CONTROL_RADIOBUTTON;

    h              = GLUI_RADIOBUTTON_SIZE;

    group          = NULL;

    orig_value     = -1;

    text_x_offset  = 18;

    can_activate   = true;

  };

};





/************************************************************/

/*                                                          */

/*               Separator class (container)                */

/*                                                          */

/************************************************************/



class GLUI_Separator : public GLUI_Control

{

public:

  void draw( int x, int y );



  GLUI_Separator( void ) {

    type         = GLUI_CONTROL_SEPARATOR;

    w            = 100;

    h            = GLUI_SEPARATOR_HEIGHT;

    can_activate = false;

  };

};





#define  GLUI_SPINNER_ARROW_WIDTH  12

#define  GLUI_SPINNER_ARROW_HEIGHT  8

#define  GLUI_SPINNER_ARROW_Y       2



#define  GLUI_SPINNER_STATE_NONE   0

#define  GLUI_SPINNER_STATE_UP     1

#define  GLUI_SPINNER_STATE_DOWN   2

#define  GLUI_SPINNER_STATE_BOTH   3



#define  GLUI_SPINNER_DEFAULT_GROWTH_EXP   1.05f





/************************************************************/

/*                                                          */

/*               Spinner class (container)                  */

/*                                                          */

/************************************************************/

 

class GLUI_Spinner : public GLUI_Control

{

public:

  int           currently_inside;

  int           state;

  float         growth, growth_exp;

  int           last_x, last_y;

  int           data_type;

  int           callback_count;

  int           last_int_val;

  float         last_float_val;

  int           first_callback;

  float         user_speed;



  GLUI_EditText *edittext;



  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int same );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  int  special_handler(	int key,int modifiers );

  

  void draw( int x, int y );

  void draw_pressed( void );

  void draw_unpressed( void );

  void draw_text( int sunken );



  void update_size( void );



  void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP);

  void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP);

  int  find_arrow( int local_x, int local_y );

  void do_drag( int x, int y );

  void do_callbacks( void );

  void draw_arrows( void );

  void do_click( void );

  void idle( void );

  int  needs_idle( void );



  char *get_text( void );



  void set_float_val( float new_val );

  void set_int_val( int new_val );

  float  get_float_val( void );

  int    get_int_val( void );

  void increase_growth( void );

  void reset_growth( void );



  void set_speed( float speed ) { user_speed = speed; };



  GLUI_Spinner( void ) {

    sprintf( name, "Spinner: %p", this );

    type         = GLUI_CONTROL_SPINNER;

    h            = GLUI_EDITTEXT_HEIGHT;

    w            = GLUI_EDITTEXT_WIDTH;

    x_off        = 0;

    y_off_top    = 0;

    y_off_bot    = 0;

    can_activate = true;

    state        = GLUI_SPINNER_STATE_NONE;

    edittext     = NULL;

    growth_exp   = GLUI_SPINNER_DEFAULT_GROWTH_EXP;

    callback_count = 0;

    first_callback = true;

    user_speed   = 1.0;

  };

};



#define  GLUI_HSLIDER_ARROW_WIDTH  16

#define  GLUI_HSLIDER_ARROW_HEIGHT 16



#define  GLUI_HSLIDER_STATE_NONE   0

#define  GLUI_HSLIDER_STATE_UP     1

#define  GLUI_HSLIDER_STATE_DOWN   2

#define  GLUI_HSLIDER_STATE_BUTTON 3

#define  GLUI_HSLIDER_STATE_TROUGH_RIGHT 4

#define  GLUI_HSLIDER_STATE_TROUGH_LEFT 5

#define  GLUI_HSLIDER_STATE_BUTTON_LEFT 6

#define  GLUI_HSLIDER_STATE_BUTTON_RIGHT 7



#define  GLUI_HSLIDER_DEFAULT_GROWTH_EXP   1.05f





/************************************************************/

/*                                                          */

/*               HSlider class (container)                  */

/*                                                          */

/************************************************************/

 

class GLUI_HSlider : public GLUI_Control

{

public:

  int           state;

	int           button_is_resizable;

	float           button_left_edge;

	float           button_right_edge;

  int           bounce_target;

  int           new_button_center;

  int           old_button_center;

  int           data_type;

  int           callback_count;

  int           last_int_val;

  float         last_float_val;

  int           first_callback;

  int           bneeds_idle;

  int           int_low, int_high;

  float         float_low, float_high;

	clock_t       last_click_time;



	int needs_idle();

	void idle();

  int  mouse_over( int state, int x, int y );

  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int same );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  int  special_handler(	int key,int modifiers );

  

  void draw( int x, int y );



  void update_size( void );



  void set_float_limits( float low, float high );

  void set_int_limits( int low, int high );

  int  locate_click( int local_x, int local_y );

  void do_callbacks( void );

  void reconcile_edge( void );

  void do_click( void );



  void set_slider_val( float lval );

  void set_slider_val( float lval, float hval );

  void set_slider_val( int lval, int hval );

	float get_slider_val();

	int sync_slider();

	float find_val( float pct );



	private:

		int redge_to_pixel(float val);

		int ledge_to_pixel(float val);

		void move_button_pixels(int nval, int &oval);

		void move_val(float dx);

		float pixel_to_redge(int val);

		float pixel_to_ledge(int val);

		void update_slider_val();



	public:

  GLUI_HSlider( void ) {

    sprintf( name, "HSlider: %p", this );

    type         = GLUI_CONTROL_HSLIDER;

    h            = GLUI_HSLIDER_HEIGHT;

    w            = GLUI_HSLIDER_WIDTH;

	  button_is_resizable = false;

	  button_left_edge    = GLUI_HSLIDER_ARROW_WIDTH;

	  button_right_edge   = GLUI_HSLIDER_ARROW_WIDTH + 10;

		int_low			 = 0;

		int_high		 = w - 2*GLUI_HSLIDER_ARROW_WIDTH - 4;

		float_low		 = (float) int_low;

		float_high		 = (float) int_high;

    x_off        = 0;

    y_off_top    = 0;

    y_off_bot    = 0;

    can_activate = true;

    state        = GLUI_HSLIDER_STATE_NONE;

    callback_count = 0;

    first_callback = true;

    bneeds_idle = 0;

    last_click_time = clock();

  };

};



/************************************************************/



/*                                                          */

/*               StaticText class                           */

/*                                                          */

/************************************************************/



class GLUI_StaticText : public GLUI_Control

{

public:

  void set_text( char *text );

  void draw( int x, int y );

  void draw_text( void );

  void update_size( void );

  void erase_text( void );



  GLUI_StaticText( void ) {

    type    = GLUI_CONTROL_STATICTEXT;

    h       = GLUI_STATICTEXT_SIZE;

    name[0] = '\0';

    can_activate  = false;

  };

};







/************************************************************/

/*                                                          */

/*                   Listbox class                          */

/*                                                          */

/************************************************************/



class GLUI_Listbox_Item : public GLUI_Node 

{

public:

  GLUI_String text;

  int         id;

};



class GLUI_Listbox : public GLUI_Control

{

public:

  GLUI_String       curr_text;

  GLUI_Listbox_Item items_list;

  int               depressed;



  int  orig_value, currently_inside;

  int  text_x_offset, title_x_offset;

  int  glut_menu_id;



  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int inside );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  key_handler( unsigned char key,int modifiers );

  int  special_handler(	int key,int modifiers );



  void update_size( void );

  void draw( int x, int y );

  int  mouse_over( int state, int x, int y );



  void draw_active_area( void );

  void set_int_val( int new_val );

  void dump( FILE *output );



  int  add_item( int id, char *text );

  int  delete_item( char *text );

  int  delete_item( int id );

  int  sort_items( void );



  int  do_selection( int item );



  void increase_width( void );



  GLUI_Listbox_Item *get_item_ptr( char *text );

  GLUI_Listbox_Item *get_item_ptr( int id );

  



  GLUI_Listbox( void ) {

    sprintf( name, "Listbox: %p", this );

    type           = GLUI_CONTROL_LISTBOX;

    w              = GLUI_EDITTEXT_WIDTH;

    h              = GLUI_EDITTEXT_HEIGHT;

    orig_value     = -1;

    title_x_offset = 0;

    text_x_offset  = 55;

    can_activate   = true;

    curr_text[0]   = '\0';

    live_type      = GLUI_LIVE_INT;  /* This has an integer live var */

    depressed      = false;

    glut_menu_id   = -1;

  };



  ~GLUI_Listbox();

};





/************************************************************/

/*                                                          */

/*              Mouse_Interaction class                     */

/*                                                          */

/************************************************************/



class GLUI_Mouse_Interaction : public GLUI_Control

{

public:

  /*int  get_main_area_size( void ) { return MIN( h-18,  */

  int            draw_active_area_only;

    

  int  mouse_down_handler( int local_x, int local_y );

  int  mouse_up_handler( int local_x, int local_y, int inside );

  int  mouse_held_down_handler( int local_x, int local_y, int inside );

  int  special_handler( int key, int modifiers );

  void update_size( void );

  void draw( int x, int y );

  void draw_active_area( void );

  

  /***  The following methods (starting with "iaction_") need to

    be overloaded  ***/

  virtual int  iaction_mouse_down_handler( int local_x, int local_y ) = 0;

  virtual int  iaction_mouse_up_handler( int local_x, int local_y, int inside )=0;

  virtual int  iaction_mouse_held_down_handler( int local_x, int local_y, int inside )=0;

  virtual int  iaction_special_handler( int key, int modifiers )=0;

  virtual void iaction_draw_active_area_persp( void )=0;

  virtual void iaction_draw_active_area_ortho( void )=0;

  virtual void iaction_dump( FILE *output )=0;

  virtual void iaction_init( void ) = 0;

  

  GLUI_Mouse_Interaction( void ) {

    sprintf( name, "Mouse_Interaction: %p", this );

    type           = GLUI_CONTROL_MOUSE_INTERACTION;

    w              = GLUI_MOUSE_INTERACTION_WIDTH;

    h              = GLUI_MOUSE_INTERACTION_HEIGHT;

    can_activate   = true;

    live_type      = GLUI_LIVE_NONE;

    alignment      = GLUI_ALIGN_CENTER;

    draw_active_area_only = false;

  };

};



 

/************************************************************/

/*                                                          */

/*                   Rotation class                         */

/*                                                          */

/************************************************************/



class GLUI_Rotation : public GLUI_Mouse_Interaction

{

public:

  Arcball        *ball;

  GLUquadricObj *quadObj;

  int            can_spin, spinning;

  float          damping;

  

  int  iaction_mouse_down_handler( int local_x, int local_y );

  int  iaction_mouse_up_handler( int local_x, int local_y, int inside );

  int  iaction_mouse_held_down_handler( int local_x, int local_y, int inside );

  int  iaction_special_handler( int key, int modifiers );

  void iaction_init( void ) { init_ball(); };

  void iaction_draw_active_area_persp( void );

  void iaction_draw_active_area_ortho( void );

  void iaction_dump( FILE *output );



  /*  void update_size( void ); */

  /*  void draw( int x, int y ); */

  /*  int mouse_over( int state, int x, int y ); */

	

  void setup_texture( void );

  void setup_lights( void );

  void draw_ball( float radius );



  void init_ball( void );



  void reset( void );



  int  needs_idle( void );

  void idle( void );



  void copy_float_array_to_ball( void );

  void copy_ball_to_float_array( void );



  void set_spin( float damp_factor );



  GLUI_Rotation(void);

};







/************************************************************/

/*                                                          */

/*                   Translation class                      */

/*                                                          */

/************************************************************/



class GLUI_Translation : public GLUI_Mouse_Interaction

{

public:

  int trans_type;  /* Is this an XY or a Z controller? */

  int down_x, down_y;

  float scale_factor;

  GLUquadricObj *quadObj;

  int   trans_mouse_code;

  float orig_x, orig_y, orig_z;

  int   locked;



  int  iaction_mouse_down_handler( int local_x, int local_y );

  int  iaction_mouse_up_handler( int local_x, int local_y, int inside );

  int  iaction_mouse_held_down_handler( int local_x, int local_y, int inside );

  int  iaction_special_handler( int key, int modifiers );

  void iaction_init( void ) {  };

  void iaction_draw_active_area_persp( void );

  void iaction_draw_active_area_ortho( void );

  void iaction_dump( FILE *output );



  void set_speed( float s ) { scale_factor = s; };



  void setup_texture( void );

  void setup_lights( void );

  void draw_2d_arrow( int radius, int filled, int orientation ); 

  void draw_2d_x_arrows( int radius );

  void draw_2d_y_arrows( int radius );

  void draw_2d_z_arrows( int radius );

  void draw_2d_xy_arrows( int radius );



  int  get_mouse_code( int x, int y );



  /* Float array is either a single float (for single-axis controls),

     or two floats for X and Y (if an XY controller) */



  float get_z( void ) {		return float_array_val[0];	}

  float get_x( void ) {		return float_array_val[0];	}

  float get_y( void ) {

    if ( trans_type == GLUI_TRANSLATION_XY )    return float_array_val[1];

    else					return float_array_val[0];

  }



  void  set_z( float val );

  void  set_x( float val );

  void  set_y( float val );

  void  set_one_val( float val, int index );



  GLUI_Translation( void ) {

    locked              = GLUI_TRANSLATION_LOCK_NONE;

    sprintf( name, "Translation: %p", this );

    type                = GLUI_CONTROL_TRANSLATION;

    w                   = GLUI_MOUSE_INTERACTION_WIDTH;

    h                   = GLUI_MOUSE_INTERACTION_HEIGHT;

    can_activate        = true;

    live_type           = GLUI_LIVE_FLOAT_ARRAY;

    float_array_size    = 0;

    alignment           = GLUI_ALIGN_CENTER;

    trans_type          = GLUI_TRANSLATION_XY;

    scale_factor        = 1.0;

    quadObj             = NULL;

    trans_mouse_code    = GLUI_TRANSLATION_MOUSE_NONE;

  };

};









/********** Misc functions *********************/

int _glutBitmapWidthString( void *font, char *s );

void _glutBitmapString( void *font, char *s );







/********** Our own callbacks for glut *********/

/* These are the callbacks that we pass to glut.  They take

   some action if necessary, then (possibly) call the user-level

   glut callbacks.  

   */



void glui_display_func( void );

void glui_reshape_func( int w, int h );

void glui_keyboard_func(unsigned char key, int x, int y);

void glui_special_func(int key, int x, int y);

void glui_mouse_func(int button, int state, int x, int y);

void glui_motion_func(int x, int y);

void glui_passive_motion_func(int x, int y);

void glui_entry_func(int state);

void glui_visibility_func(int state);

void glui_idle_func(void);



void glui_parent_window_reshape_func( int w, int h );

void glui_parent_window_keyboard_func(unsigned char key, int x, int y);

void glui_parent_window_mouse_func(int, int, int, int );

void glui_parent_window_special_func(int key, int x, int y);







#endif

